package ltd.nullpointer.frontend.web.controller.api;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.metadata.Sheet;
import com.boot2.core.HlAssert;
import com.boot2.core.utils.BeanUtils;
import com.boot2.core.utils.DateUtil;
import com.boot2.core.utils.FileUtil;
import com.boot2.core.utils.ZipUtil;
import com.boot2.core.vo.Response;
import com.boot2.core.web.validator.FileUpload;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.apachecommons.CommonsLog;
import ltd.nullpointer.frontend.dao.SensorDataDao;
import ltd.nullpointer.frontend.facade.SensorMessageUpFacade;
import ltd.nullpointer.frontend.model.entity.up.SensorData;
import ltd.nullpointer.frontend.service.NpAtrributeKvService;
import ltd.nullpointer.frontend.web.controller.ApiBaseController;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;

/**
 * @author zhangweilin
 * @date 2019/5/7 14:38
 * @Description: 导入
 */
@Api(tags = "导入")
@RestController
@RequestMapping("/user/import")
@CommonsLog
public class ImportController extends ApiBaseController {

    @Autowired
    SensorDataDao sensorDataDao;

    @Autowired
    SensorMessageUpFacade sensorMessageUpFacade;

    @Autowired
    NpAtrributeKvService npAtrributeKvService;

    @ApiOperation(value = "导入传感器测量数据(xls,xlsx,zip格式)")
    @PostMapping("/uploadSensorData")
    @FileUpload(suffixs = "xls,xlsx,zip", maxSize = 10 * 1000 * 1000, maxNum = 1)
    public Response<Void> uploadXlsx(@ApiParam(value = "多文件上传", required = true) MultipartFile file,
                                     @ApiParam(value = "是否删除原数据", required = false, defaultValue = "false")
                                     @RequestParam(value = "delete", required = false, defaultValue = "false") boolean delete,
                                     @RequestParam @ApiParam(value = "删除数据开始时间, 默认从1970-01-01 00:00:00", required = false) Date timeFrom,
                                     @RequestParam @ApiParam(value = "删除数据结束时间, 默认到当前时间", required = false) Date timeTo,
                                     @ApiParam(value = "是否修正原数据", required = false, defaultValue = "false")
                                         @RequestParam(value = "calibrate", required = false, defaultValue = "false") boolean calibrate) throws IOException {
        HlAssert.notNull(file, "文件无效");
//        HlAssert.isTrue(CollectionUtils.isNotEmpty(dataList), "excel内容为空");
        String originalFilename = file.getOriginalFilename();
//        System.out.println("originalFilename = " + originalFilename);
        File file0 = new File(originalFilename);
        FileUtils.copyInputStreamToFile(file.getInputStream(), file0);

        //如果上传的是zip
        if (originalFilename.endsWith(".zip")) {
            File file2 = ZipUtil.unZip(file0.getAbsolutePath());
//            System.out.println("file2 = " + file2);
            ArrayList<File> fileList = FileUtil.getAllFile(file2);
            log.info("上传了压缩文件，解压后共【"+fileList.size()+"】个excel文件");
            for (File file1 : fileList) {
                handSensorData(file1, delete, calibrate, timeFrom, timeTo);
            }
        }else{
            handSensorData(file0, delete, calibrate, timeFrom, timeTo);
        }
        return success();
    }

    private void handSensorData(File file1, boolean delete, boolean calibrate, Date time0, Date time1) throws FileNotFoundException {
        List<Object> dataList = EasyExcelFactory.read(new BufferedInputStream(new FileInputStream(file1)), new Sheet(1, 1));
        log.info("解析文件:"+file1+", 共【"+dataList.size()+"】条数据");
        if (delete && dataList.size() > 0) {
            log.warn("删除原数据！！！");
            List<Object> objects = (List<Object>) dataList.get(0);
            Date timeFrom = new Date(1970, Calendar.JANUARY, 1);
            if (time0 != null) timeFrom = time0;
            Date timeTo = new Date();
            if (time1 != null) timeTo = time1;
            sensorDataDao.deleteBySensorNo((String) objects.get(0), timeFrom, timeTo);
            sensorDataDao.flush();
        }
        for (Object object : dataList) {
            List<Object> objectList = (List<Object>) object;
            Object sensorNoObj = objectList.get(0);
            Object sensorSelfNoObj = objectList.get(1);
            Object modelObj = objectList.get(2);
            Object dateObj = objectList.get(3);
            Object timeObj = objectList.get(4);
            Object tempObj = objectList.get(5);
            Object measurementObj = objectList.get(6);
            Object deviationObj = objectList.get(7);
            Object unitObj = objectList.get(8);
            Object strainFreObj = objectList.get(9);
            Object comFreObj = objectList.get(10);
            Object typeObj = objectList.get(11);
            if(sensorNoObj == null || dateObj == null ||
                    timeObj == null || tempObj == null ||
                    measurementObj == null || deviationObj == null) {
                continue;
            }
            String sensorNoStr = String.valueOf(sensorNoObj);
            String sensorSelfNoStr = String.valueOf(sensorSelfNoObj);
            String modelStr = String.valueOf(modelObj);
            String dateStr = String.valueOf(dateObj);
            String timeStr = String.valueOf(timeObj);
            String tempStr = String.valueOf(tempObj);
            String measurementStr = String.valueOf(measurementObj);
            String deviationStr = String.valueOf(deviationObj);
            String unitStr =String.valueOf(unitObj);
            String strainFreStr = String.valueOf(strainFreObj);
            String comFreStr = String.valueOf(comFreObj);
            String typeStr = String.valueOf(typeObj);
            if ("".equals(sensorNoStr.trim()) || "".equals(dateStr.trim()) ||
                "".equals(timeStr.trim()) || "".equals(tempStr.trim()) ||
                "".equals(measurementStr.trim()) || "".equals(deviationStr.trim())) {
                continue;
            }
            SensorData sensorData = new SensorData();
            sensorData.setSensorNo(sensorNoStr);
            sensorData.setSensorSelfNo(sensorSelfNoStr);
            sensorData.setModel(modelStr);
            if(dateStr.contains("/")) {
                dateStr = dateStr.replace("/", "-");
            } else if(dateStr.contains("年") || dateStr.contains("月") || dateStr.contains("日")) {
                dateStr = dateStr.replaceAll("[年,月]", "-");
                dateStr = dateStr.replace("日", "");
            }
            sensorData.setMeasuringTime(DateUtil.getFormatDate(dateStr + " " + timeStr, "yyyy-MM-dd HH:mm:ss"));
            sensorData.setTemp(new BigDecimal(tempStr));
            sensorData.setMeasurement(new BigDecimal(measurementStr));
            sensorData.setDeviation(new BigDecimal(deviationStr));
            sensorData.setUnit(unitStr);
            sensorData.setStrainFre(new BigDecimal(strainFreStr!=null?strainFreStr:"0"));
            sensorData.setComFre(new BigDecimal(comFreStr!=null?comFreStr:"0"));
            sensorData.setType(Integer.valueOf(typeStr!=null?typeStr:"0"));
            sensorData.setCreateTime();
            sensorData.setOriginalMeasure(sensorData.getMeasurement());
            //在此处利用公式修正测量值
            if (calibrate) {
                Map<String, Double> allAttributeKv = npAtrributeKvService.selectAllAttributeKv(sensorData.getSensorNo());
                Double initialValue = allAttributeKv.get("initial_value") == null ? 0.0 : allAttributeKv.get("initial_value");
                Double height = allAttributeKv.get("height") == null ? 0.0 : allAttributeKv.get("height");
                Double depth = allAttributeKv.get("depth") == null ? 0.0 : allAttributeKv.get("depth");
                Double ratio = allAttributeKv.get("ratio") == null ? 1.0 : allAttributeKv.get("ratio");
                Double controlFlag = allAttributeKv.get("control_flag");
                if (controlFlag != null && controlFlag == 1) {
                    Double height2 = height - depth + ratio * (sensorData.getMeasurement().doubleValue() - initialValue);
                    sensorData.setMeasurement(new BigDecimal(height2));
                }
            }
            SensorData sensorData2 = new SensorData();
            sensorData2.setSensorNo(sensorData.getSensorNo());
            sensorData2.setMeasuringTime(sensorData.getMeasuringTime());
            List<SensorData> oldSensorDatas = sensorDataDao.findAll(Example.of(sensorData2));
            if (oldSensorDatas != null && oldSensorDatas.size() > 0) {
                log.info("已经存在该数据，数量: " + oldSensorDatas.size());
                if (oldSensorDatas.size() == 1) {
                    log.info("更新该数据，sensorNo: " + sensorData.getSensorNo()  + " measuringTime:" + sensorData.getMeasuringTime());
                    BeanUtils.copyProperties(sensorData, oldSensorDatas.get(0));
                    sensorDataDao.saveAndFlush(oldSensorDatas.get(0));
                    sensorMessageUpFacade.sendSensorData(oldSensorDatas.get(0));
                    continue;
                } else {
                    log.warn("删除所有已存在的重复记录，数量: " + oldSensorDatas.size());
                    sensorDataDao.deleteInBatch(oldSensorDatas);
                    sensorDataDao.flush();
                }
            }
            log.info("插入新数据，sensorNo: " + sensorData.getSensorNo()  + " measuringTime:" + sensorData.getMeasuringTime());
            sensorDataDao.saveAndFlush(sensorData);
            sensorMessageUpFacade.sendSensorData(sensorData);
        }
    }


}
